//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "cevent.h"
#include "cthread.h"
#include "pseudo.h"
#include "helper.h"
#include <aura.h>
#include <elacs.h>

CEvent::~CEvent()
{
    if (NULL != m_hEvent) {
        AuraEvent_Destroy(m_hEvent);
        m_hEvent = NULL;
    }
}

ECode CEvent::Initialize(
    /* [in] */ Boolean bManualReset,
    /* [in] */ EventState initialState)
{
    return (ECode)AuraEvent_Create((Aura_Bool)bManualReset, (Aura_EventState)initialState, &m_hEvent);
}

PInterface CEvent::Probe(
    /* [in]  */ REIID riid)
{
    if (riid == EIID_IInterface) {
        return (PInterface)(IEvent *)this;
    }
    else if (riid == EIID_IEvent) {
        return (IEvent *)this;
    }
    else if (riid == EIID_CLASS_INFO) {
        return (PInterface)&ECLSID_CEvent;
    }
    else if (riid == EIID_INTERFACE_INFO) {
        return (PInterface)&EIID_IEvent;
    }

    return NULL;
}

UInt32 CEvent::AddRef()
{
    Int32 nRef = m_cRef.Increment();
    return (UInt32)nRef;
}

UInt32 CEvent::Release()
{
    Int32 nRef = m_cRef.Decrement();
    if (nRef == 0) {
        delete this;
    }
    return (UInt32)nRef;
}

ECode CEvent::Aggregate(
    /* [in]  */ AggregateType type,
    /* [in]  */ PInterface pObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CEvent::GetDomain(
    /* [out] */ PInterface * ppObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CEvent::Wait(
    /* [out] */ WaitResult * pResult,
    /* [out] */ EventState * pState)
{
    if (NULL == pResult) {
        return E_INVALID_ARGUMENT;
    }

    return TryWait(INFINITE, pResult, pState);
}

ECode CEvent::TryWait(
    /* [in]  */ Millisecond32 msTimeout,
    /* [out] */ WaitResult * pResult,
    /* [out] */ EventState * pState)
{
    CThread * pThread = NULL;
    ECode ec = NOERROR;

    if (NULL == pResult) {
        return E_INVALID_ARGUMENT;
    }

    PVoid pLock = _Elastos_SequencedContext_Leave();

    pThread = (CThread *)GetCurrentThread_Expected();
    pThread->SetThreadState(ThreadState_Sleeping);
    ec = (ECode)AuraEvent_Wait(m_hEvent,
        (Aura_Millisecond32)msTimeout,
        (Aura_WaitResult *)pResult,
        (Aura_EventState *)pState);
    pThread->SetThreadState(ThreadState_Running);

    _Elastos_SequencedContext_Enter(pLock);

    return ec;
}

ECode CEvent::Notify(
    /* [in ] */ EventState dwState)
{
    if (UNSIGNALED == dwState) {
        return E_INVALID_ARGUMENT;
    }

    return (ECode)AuraEvent_Signal(m_hEvent, (Aura_EventState)dwState);
}

ECode CEvent::Clear()
{
    return (ECode)AuraEvent_Unsignal(m_hEvent);
}

// static member function to create event.-----
ECode CEvent::S_Create(
    /* [in] */ Boolean bManualReset,
    /* [in] */ EventState initialState,
    /* [out] */ IEvent ** ppEvent)
{
    CEvent * pEvent = NULL;
    ECode ec = NOERROR;

    assert(NULL != ppEvent);
    pEvent = new CEvent();
    if (NULL == pEvent) {
        ec = E_OUT_OF_MEMORY;
        goto ErrorExit;
    }
    ec = pEvent->Initialize(bManualReset, initialState);
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    *ppEvent = (IEvent *)pEvent;
    (*ppEvent)->AddRef();

    return NOERROR;

ErrorExit:
    if (NULL != pEvent) {
        delete pEvent;
        pEvent = NULL;
    }
    return ec;
}

